package com.example.verify.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.verify.constant.CacheNameConstant;
import com.example.verify.constant.SecurityConstant;
import com.example.verify.constant.TokenConstant;
import com.example.verify.tools.PatternUtil;
import com.example.verify.tools.ServletUtil;
import com.example.common.web.domain.Result;
import com.example.common.web.domain.ResultCode;
import com.example.common.web.exception.auth.token.TokenExpiredException;
import com.example.common.web.exception.auth.token.TokenValidationException;
import com.example.verify.context.BeanContext;
import com.example.verify.pojo.SecureUser;
import com.example.verify.pojo.SecureUserToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import org.apache.commons.codec.binary.Base64;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;


/**
 * Token Filter 主要增加 Token 的验证
 *
 * Author: 就 眠 仪 式
 * CreateTime: 2021/03/27
 * */
public class SecureUserTokenSupport extends OncePerRequestFilter {

    @Autowired
    private BeanContext beanContext;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String token = request.getHeader(TokenConstant.SERVICE_TOKEN);
        // token param verify empty
        if (token == null) { ServletUtil.writeJson(Result.failure(ResultCode.TOKEN_MISSION)); return;}
        // token verify
        SecureUser secureUser;
        try {
            String userToeknString = new String(Base64.decodeBase64(token));
            SecureUserToken userToken = taskToken(userToeknString);
            secureUser = userToken.getSecureUser();
        }catch (TokenValidationException e){
            ServletUtil.writeJson(Result.failure(ResultCode.TOKEN_INVALID)); return;
        }catch (TokenExpiredException e){
            ServletUtil.writeJson(Result.failure(ResultCode.TOKEN_EXPIRED)); return;
        }
        // return UsernamePasswordAuthenticationToken
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(secureUser, secureUser.getId(), secureUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);
    }


    // TODO 修正匹配策略
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        List<String> pattern = Arrays.asList(SecurityConstant.HTTP_ACT_MATCHERS.split(","));
        return PatternUtil.matches(pattern, ServletUtil.getRequestURI());
    }

    public SecureUserToken taskToken(String userStr){

        // 反序列化，但authorities反序列化失败,需要手动注入
        SecureUserToken secureUserToken = JSONObject.parseObject(userStr, SecureUserToken.class);

        // 获取jsonAuthorities
        JSONArray jsonAuthorities = JSONObject.parseObject(userStr).getJSONObject("secureUser").getJSONArray("authorities");

        // 循环注入当前用户权限
        HashSet<SimpleGrantedAuthority> authorities=new HashSet<>();
        for (int i = 0; i < jsonAuthorities.size(); i++) {
            authorities.add(new SimpleGrantedAuthority(jsonAuthorities.getJSONObject(i).get("authority").toString()));
        }
        secureUserToken.getSecureUser().deserializeAuthorities(authorities);

        return secureUserToken;
    }
}
